home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / do.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  31.0 KB  |  1,256 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)do.c    3.1    93/06/26    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /* Contains code for 'd', 'D' (drop), '>', '<' (up, down) */
  6.  
  7. #include "hack.h"
  8. #include "lev.h"
  9.  
  10. #include <errno.h>
  11. #ifdef _MSC_VER    /* MSC 6.0 defines errno quite differently */
  12. # if (_MSC_VER >= 600)
  13. #  define SKIP_ERRNO
  14. # endif
  15. #endif
  16. #ifndef SKIP_ERRNO
  17. extern int errno;
  18. #endif
  19.  
  20. #ifdef MFLOPPY
  21. extern struct finfo fileinfo[];
  22. #else
  23. extern boolean level_exists[];
  24. #endif
  25.  
  26. #ifdef SINKS
  27. # ifdef OVLB
  28. static void FDECL(trycall, (struct obj *));
  29. # endif /* OVLB */
  30. STATIC_DCL void FDECL(dosinkring, (struct obj *));
  31. #endif /* SINKS */
  32.  
  33. STATIC_PTR int FDECL(drop, (struct obj *));
  34. STATIC_PTR int NDECL(wipeoff);
  35.  
  36. #ifdef OVL2
  37. static int NDECL(currentlevel_rewrite);
  38. /* static boolean FDECL(badspot, (XCHAR_P,XCHAR_P)); */
  39. #endif
  40.  
  41. #ifdef OVLB
  42.  
  43. static NEARDATA const char drop_types[] =
  44.     { ALLOW_COUNT, GOLD_CLASS, ALL_CLASSES, 0 };
  45.  
  46. int
  47. dodrop()
  48. {
  49.     int result;
  50.  
  51.     if (*u.ushops) sellobj_state(TRUE);
  52.     result = drop(getobj(drop_types, "drop"));
  53.     if (*u.ushops) sellobj_state(FALSE);
  54.     reset_occupations();
  55.  
  56.     return result;
  57. }
  58.  
  59. #endif /* OVLB */
  60. #ifdef OVL0
  61.  
  62. /* Called when a boulder is dropped, thrown, or pushed.  If it ends up
  63.  * in a pool, it either fills the pool up or sinks away.  In either case,
  64.  * it's gone for good...  If the destination is not a pool, returns FALSE.
  65.  */
  66. boolean
  67. boulder_hits_pool(otmp, rx, ry, pushing)
  68. struct obj *otmp;
  69. register int rx, ry;
  70. boolean pushing;
  71. {
  72.     if (!otmp || otmp->otyp != BOULDER)
  73.         impossible("Not a boulder?");
  74.     else if (!Is_waterlevel(&u.uz) && (is_pool(rx,ry) || is_lava(rx,ry))) {
  75.         boolean lava = is_lava(rx,ry), fills_up;
  76.         const char *what = lava ? "lava" : "water";
  77.         schar ltyp = levl[rx][ry].typ;
  78.         int chance = rn2(10);        /* water: 90%; lava: 10% */
  79.         fills_up = lava ? chance == 0 : chance != 0;
  80.  
  81.         if (fills_up) {
  82.         if (ltyp == DRAWBRIDGE_UP) {
  83.             levl[rx][ry].drawbridgemask &= ~DB_UNDER; /* clear lava */
  84.             levl[rx][ry].drawbridgemask |= DB_FLOOR;
  85.         } else
  86.             levl[rx][ry].typ = ROOM;
  87.  
  88.         bury_objs(rx, ry);
  89.         newsym(rx,ry);
  90.         if (pushing) {
  91.             You("push %s into the %s.", the(xname(otmp)), what);
  92.             if (flags.verbose && !Blind)
  93.             pline("Now you can cross it!");
  94.             /* no splashing in this case */
  95.         }
  96.         }
  97.         if (!fills_up || !pushing) {    /* splashing occurs */
  98.         if (!u.uinwater) {
  99.             if (pushing ? !Blind : cansee(rx,ry)) {
  100.             boolean moat = (ltyp != WATER) &&
  101.                 !Is_medusa_level(&u.uz) && !Is_waterlevel(&u.uz);
  102.  
  103.             pline("There is a large splash as %s %s the %s.",
  104.                   the(xname(otmp)), fills_up? "fills":"falls into",
  105.                   lava ? "lava" : ltyp==POOL ? "pool" :
  106.                   moat ? "moat" : "water");
  107.             } else if (flags.soundok)
  108.             You("hear a%s splash.", lava ? " sizzling" : "");
  109.             wake_nearby();
  110.         }
  111.  
  112.         if (fills_up && u.uinwater && distu(rx,ry) == 0) {
  113.             u.uinwater = 0;
  114.             docrt();
  115.             vision_full_recalc = 1;
  116.             You("find yourself on dry land again!");
  117.         } else if (lava && distu(rx,ry) <= 2) {
  118.             You("are hit by molten lava%c",
  119.             Fire_resistance ? '.' : '!');
  120.             losehp(d((Fire_resistance ? 1 : 3), 6),
  121.                "molten lava", KILLED_BY);
  122.         } else if (!fills_up && flags.verbose &&
  123.                (pushing ? !Blind : cansee(rx,ry)))
  124.             pline("It sinks without a trace!");
  125.         }
  126.  
  127.         /* boulder is now gone */
  128.         if (pushing) delobj(otmp);
  129.         else obfree(otmp, (struct obj *)0);
  130.         return TRUE;
  131.     }
  132.     return FALSE;
  133. }
  134.  
  135. /* Used for objects which sometimes do special things when dropped; must be
  136.  * called with the object not in any chain.  Returns 1 if the object is
  137.  * gone.
  138.  */
  139. boolean
  140. flooreffects(obj,x,y,verb)
  141. struct obj *obj;
  142. int x,y;
  143. const char *verb;
  144. {
  145.     struct trap *t;
  146.  
  147.     /* make sure things like water_damage() have no pointers to follow */
  148.     obj->nobj = obj->nexthere = (struct obj *)0;
  149.  
  150.     if (obj->otyp == BOULDER && boulder_hits_pool(obj, x, y, FALSE))
  151.         return TRUE;
  152.     else if (obj->otyp == BOULDER && (t = t_at(x,y)) != 0 &&
  153.          (t->ttyp==PIT || t->ttyp==SPIKED_PIT || t->ttyp==TRAPDOOR)) {
  154.         struct monst *mtmp;
  155.  
  156.         if(!Can_fall_thru(&u.uz) && t->ttyp == TRAPDOOR)
  157.             return FALSE;
  158.         if (((mtmp = m_at(x, y)) && mtmp->mtrapped) ||
  159.             (u.utrap && x==u.ux && y==u.uy)) {
  160.             /* u.utrap = 0;     /* player remains trapped. See trap.c */
  161.             if (*verb)
  162.             pline("The boulder %ss into the pit%s.", verb,
  163.                 (mtmp) ? "" : " with you");
  164.             if (mtmp) {
  165.             if (!passes_walls(mtmp->data) && !throws_rocks(mtmp->data))
  166.                 if (hmon(mtmp, obj, TRUE))
  167.                     return FALSE;    /* still alive */
  168.             } else
  169. #ifdef POLYSELF
  170.             if (!passes_walls(uasmon) && !throws_rocks(uasmon))
  171. #endif
  172.             {
  173.                 losehp(rnd(15), "squished under a boulder",
  174.                     NO_KILLER_PREFIX);
  175.                 return FALSE;
  176.             }
  177.         }
  178.         if (*verb) {
  179.             if (Blind) {
  180.                 if ((x == u.ux) && (y == u.uy))
  181.                     You("hear a CRASH! beneath you.");
  182.                 else
  183.                     You("hear the boulder %s.", verb);
  184.             } else if (cansee(x, y)) {
  185.                 pline("The boulder %sfills a %s.",
  186.                      t->tseen ? "" : "triggers and ",
  187.                      t->ttyp == TRAPDOOR ?
  188.                      "trap door" : "pit");
  189.             }
  190.         }
  191.         deltrap(t);
  192.         obfree(obj, (struct obj *)0);
  193.         bury_objs(x, y);
  194.         newsym(x,y);
  195.         return TRUE;
  196.     } else if (is_pool(x, y)) {
  197.         water_damage(obj, FALSE, FALSE);
  198.     }
  199.     return FALSE;
  200. }
  201.  
  202. #endif /* OVL0 */
  203. #ifdef OVLB
  204.  
  205. void
  206. doaltarobj(obj)  /* obj is an object dropped on an altar */
  207.     register struct obj *obj;
  208. {
  209.     if (Blind) return;
  210.     if (obj->blessed || obj->cursed) {
  211.         pline("There is %s flash as %s hit%s the altar.",
  212.             an(Hallucination ? hcolor() :
  213.                 obj->blessed ? amber : Black),
  214.             doname(obj),
  215.             (obj->quan == 1L) ? "s" : "");
  216.         if (!Hallucination) obj->bknown = 1;
  217.     } else {
  218.         pline("%s land%s on the altar.", Doname2(obj),
  219.             (obj->quan == 1L) ? "s" : "");
  220.         obj->bknown = 1;
  221.     }
  222. }
  223.  
  224. #ifdef SINKS
  225. static
  226. void
  227. trycall(obj)
  228. register struct obj *obj;
  229. {
  230.     if(!objects[obj->otyp].oc_name_known &&
  231.        !objects[obj->otyp].oc_uname)
  232.        docall(obj);
  233. }
  234.  
  235. STATIC_OVL
  236. void
  237. dosinkring(obj)  /* obj is a ring being dropped over a kitchen sink */
  238. register struct obj *obj;
  239. {
  240.     register struct obj *otmp,*otmp2;
  241.     register boolean ideed = TRUE;
  242.  
  243.     You("drop %s down the drain.", doname(obj));
  244. #ifndef NO_SIGNAL
  245.     obj->in_use = TRUE;    /* block free identification via interrupt */
  246. #endif
  247.     switch(obj->otyp) {    /* effects that can be noticed without eyes */
  248.         case RIN_SEARCHING:
  249.         You("thought your %s got lost in the sink, but there it is!",
  250.             xname(obj));
  251. #ifndef NO_SIGNAL
  252.         obj->in_use = FALSE;
  253. #endif
  254.         dropx(obj);
  255.         trycall(obj);
  256.         return;
  257.         case RIN_LEVITATION:
  258.         pline("The sink quivers upward for a moment.");
  259.         break;
  260.         case RIN_POISON_RESISTANCE:
  261. #ifdef TUTTI_FRUTTI
  262.         You("smell rotten %s.", makeplural(pl_fruit));
  263. #else
  264.         You("smell rotten fruit.");
  265. #endif
  266.         break;
  267.         case RIN_AGGRAVATE_MONSTER:
  268.         pline("Several flies buzz angrily around the sink.");
  269.         break;
  270.         case RIN_SHOCK_RESISTANCE:
  271.         pline("Static electricity surrounds the sink.");
  272.         break;
  273.         case RIN_CONFLICT:
  274.         You("hear loud noises coming from the drain.");
  275.         break;
  276.         case RIN_GAIN_STRENGTH:
  277.         pline("The water flow seems %ser now.",
  278.             (obj->spe<0) ? "weak" : "strong");
  279.         break;
  280.         case RIN_INCREASE_DAMAGE:
  281.         pline("The water's force seems %ser now.",
  282.             (obj->spe<0) ? "small" : "great");
  283.         break;
  284.         default:
  285.         ideed = FALSE;
  286.         break;
  287.     }
  288.     if(!Blind && !ideed) {
  289.         ideed = TRUE;
  290.         switch(obj->otyp) {        /* effects that need eyes */
  291.         case RIN_ADORNMENT:
  292.             pline("The faucets flash brightly for a moment.");
  293.             break;
  294.         case RIN_REGENERATION:
  295.             pline("The sink looks as good as new.");
  296.             break;
  297.         case RIN_INVISIBILITY:
  298.             You("don't see anything happen to the sink.");
  299.             break;
  300.         case RIN_SEE_INVISIBLE:
  301.             You("see some air in the sink.");
  302.             break;
  303.         case RIN_STEALTH:
  304.         pline("The sink seems to blend into the floor for a moment.");
  305.             break;
  306.         case RIN_HUNGER:
  307.             ideed = FALSE;
  308.             for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp2) {
  309.             otmp2 = otmp->nexthere;
  310.             if(otmp != uball && otmp != uchain) {
  311.                 pline("Suddenly, %s vanishes from the sink!",
  312.                             doname(otmp));
  313.                 delobj(otmp);
  314.                 ideed = TRUE;
  315.             }
  316.             }
  317.             break;
  318.         case RIN_FIRE_RESISTANCE:
  319.         pline("The hot water faucet flashes brightly for a moment.");
  320.             break;
  321.         case RIN_COLD_RESISTANCE:
  322.         pline("The cold water faucet flashes brightly for a moment.");
  323.             break;
  324.         case RIN_PROTECTION_FROM_SHAPE_CHAN:
  325.             pline("The sink looks nothing like a fountain.");
  326.             break;
  327.         case RIN_PROTECTION:
  328.             pline("The sink glows %s for a moment.",
  329.                 Hallucination ? hcolor() :
  330.                 (obj->spe<0) ? Black : silver);
  331.             break;
  332.         case RIN_WARNING:
  333.             pline("The sink glows %s for a moment.",
  334.                 Hallucination ? hcolor() : White);
  335.             break;
  336.         case RIN_TELEPORTATION:
  337.             pline("The sink momentarily vanishes.");
  338.             break;
  339.         case RIN_TELEPORT_CONTROL:
  340.         pline("The sink looks like it is being beamed aboard somewhere.");
  341.             break;
  342. #ifdef POLYSELF
  343.         case RIN_POLYMORPH:
  344.             pline("The sink momentarily looks like a fountain.");
  345.             break;
  346.         case RIN_POLYMORPH_CONTROL:
  347.     pline("The sink momentarily looks like a regularly erupting geyser.");
  348.             break;
  349. #endif
  350.         }
  351.     }
  352.     if(ideed)
  353.         trycall(obj);
  354.     else
  355.         You("hear the ring bouncing down the drainpipe.");
  356.     if (!rn2(20)) {
  357.         pline("The sink backs up, leaving %s.", doname(obj));
  358. #ifndef NO_SIGNAL
  359.         obj->in_use = FALSE;
  360. #endif
  361.         dropx(obj);
  362.     }
  363.     else
  364.         useup(obj);
  365. }
  366. #endif
  367.  
  368. #endif /* OVLB */
  369. #ifdef OVL0
  370.  
  371. /* some common tests when trying to drop or throw items */
  372. boolean
  373. canletgo(obj,word)
  374. register struct obj *obj;
  375. register const char *word;
  376. {
  377.     if(obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)){
  378.         if (*word)
  379.             Norep("You cannot %s something you are wearing.",word);
  380.         return(FALSE);
  381.     }
  382.     if (obj->otyp == LOADSTONE && obj->cursed) {
  383.         if (*word)
  384.             pline("For some reason, you cannot %s the stone%s!",
  385.                 word, plur(obj->quan));
  386.         /* Kludge -- see invent.c */
  387.         if (obj->corpsenm) {
  388.             struct obj *otmp;
  389.  
  390.             otmp = obj;
  391.             obj = obj->nobj;
  392.             obj->quan += otmp->quan;
  393.             obj->owt = weight(obj);
  394.             freeinv(otmp);
  395.             obfree(otmp, obj);
  396.         }
  397.         obj->bknown = 1;
  398.         return(FALSE);
  399.     }
  400. #ifdef WALKIES
  401.     if (obj->otyp == LEASH && obj->leashmon != 0) {
  402.         if (*word)
  403.             pline ("The leash is tied around your %s.",
  404.                     body_part(HAND));
  405.         return(FALSE);
  406.     }
  407. #endif
  408.     return(TRUE);
  409. }
  410.  
  411. STATIC_PTR
  412. int
  413. drop(obj)
  414. register struct obj *obj;
  415. {
  416.     if(!obj) return(0);
  417.     if(!canletgo(obj,"drop"))
  418.         return(0);
  419.     if(obj == uwep) {
  420.         if(welded(uwep)) {
  421.             weldmsg(obj, FALSE);
  422.             return(0);
  423.         }
  424.         setuwep((struct obj *)0);
  425.         if(uwep) return 0; /* lifesaved and rewielded */
  426.     }
  427. #ifdef SINKS
  428.     if((obj->oclass == RING_CLASS) && IS_SINK(levl[u.ux][u.uy].typ)
  429.                             && !u.uswallow) {
  430.         dosinkring(obj);
  431.         return(1);
  432.     }
  433. #endif
  434.     if (Levitation && !(Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ||
  435.                 is_pool(u.ux, u.uy) || u.uswallow)) {
  436.         if(flags.verbose) You("drop %s.", doname(obj));
  437.         if (obj->otyp != GOLD_PIECE) freeinv(obj);
  438.         (void) snuff_candle(obj);
  439.         hitfloor(obj);
  440.         return(1);
  441.     }
  442.     if (IS_ALTAR(levl[u.ux][u.uy].typ) && !u.uswallow) {
  443.         doaltarobj(obj);    /* set bknown */
  444.     } else
  445.         if(flags.verbose) You("drop %s.", doname(obj));
  446.     dropx(obj);
  447.     return(1);
  448. }
  449.  
  450. /* Called in several places - should not produce texts */
  451. void
  452. dropx(obj)
  453. register struct obj *obj;
  454. {
  455.     /* Money is *not* in our inventory */
  456.     if (obj->otyp != GOLD_PIECE) freeinv(obj);
  457.     (void) snuff_candle(obj);
  458.     if(!u.uswallow && obj != uball &&
  459.               ship_object(obj, u.ux, u.uy, FALSE)) return;
  460.     dropy(obj);
  461. }
  462.  
  463. void
  464. dropy(obj)
  465. register struct obj *obj;
  466. {
  467.     if (!u.uswallow && flooreffects(obj,u.ux,u.uy,"drop")) return;
  468.     if(obj->otyp == CRYSKNIFE)
  469.         obj->otyp = WORM_TOOTH;
  470.     (void) snuff_candle(obj);
  471.     /* uswallow check done by GAN 01/29/87 */
  472.     if(u.uswallow) {
  473.         if (obj != uball) {        /* mon doesn't pick up ball */
  474.             mpickobj(u.ustuck,obj);
  475.         }
  476.     } else  {
  477.         obj->nobj = fobj;
  478.         fobj = obj;
  479.         place_object(obj, u.ux, u.uy);
  480.         if (obj == uball)
  481.             drop_ball(u.ux,u.uy);
  482.         else
  483.             sellobj(obj, u.ux, u.uy);
  484.         stackobj(obj);
  485.         if(Blind && Levitation)
  486.             map_object(obj, 0);
  487.         newsym(u.ux,u.uy);    /* remap location under self */
  488.     }
  489. }
  490.  
  491. /* drop several things */
  492. int
  493. doddrop()
  494. {
  495.     int result;
  496.  
  497.     if (*u.ushops) sellobj_state(TRUE);
  498.     result = ggetobj("drop", drop, 0);
  499.     if (*u.ushops) sellobj_state(FALSE);
  500.     reset_occupations();
  501.  
  502.     return result;
  503. }
  504.  
  505. #endif /* OVL0 */
  506. #ifdef OVL2
  507.  
  508. /* on a ladder, used in goto_level */
  509. static NEARDATA boolean at_ladder = FALSE;
  510.  
  511. int
  512. dodown()
  513. {
  514.     struct trap *trap = 0;
  515.  
  516.     if( (u.ux != xdnstair || u.uy != ydnstair)
  517.          && (!xdnladder || u.ux != xdnladder || u.uy != ydnladder)
  518.          && (!sstairs.sx || u.ux != sstairs.sx || u.uy != sstairs.sy
  519.             || sstairs.up)
  520.       ) {
  521.         if (!(trap = t_at(u.ux,u.uy)) || trap->ttyp != TRAPDOOR
  522.             || !Can_fall_thru(&u.uz) || !trap->tseen) {
  523.             You("can't go down here.");
  524.             return(0);
  525.         }
  526.     }
  527.     if(u.ustuck) {
  528.         You("are being held, and cannot go down.");
  529.         return(1);
  530.     }
  531.     if(Levitation) {
  532.         pline("You're floating high above the %s.",
  533.             levl[u.ux][u.uy].typ == STAIRS ? "stairs" :
  534.             levl[u.ux][u.uy].typ == LADDER ? "ladder" :
  535.             "trap door");
  536.         return(0);
  537.     }
  538.     if (on_level(&valley_level, &u.uz) && !u.uevent.gehennom_entered) {
  539.         You("are standing at the gate to Gehennom.");
  540.         pline("Unspeakable cruelty and harm lurk down there.");
  541.         if (yn("Are you sure you want to enter?") != 'y')
  542.             return(0);
  543.         else pline("So be it.");
  544.         u.uevent.gehennom_entered = 1;    /* don't ask again */
  545.     }
  546.  
  547. #ifdef WALKIES
  548.     if(!next_to_u()) {
  549.         You("are held back by your pet!");
  550.         return(0);
  551.     }
  552. #endif
  553.     if (trap)
  554. #ifdef POLYSELF
  555.         You("%s into the trap door.", locomotion(uasmon, "jump"));
  556. #else
  557.         You("jump into the trap door.");
  558. #endif
  559.     if (levl[u.ux][u.uy].typ == LADDER) at_ladder = TRUE;
  560.     next_level(!trap);
  561.     at_ladder = FALSE;
  562.     return(1);
  563. }
  564.  
  565. int
  566. doup()
  567. {
  568.     if( (u.ux != xupstair || u.uy != yupstair)
  569.          && (!xupladder || u.ux != xupladder || u.uy != yupladder)
  570.          && (!sstairs.sx || u.ux != sstairs.sx || u.uy != sstairs.sy
  571.             || !sstairs.up)
  572.       ) {
  573.         You("can't go up here.");
  574.         return(0);
  575.     }
  576.     if(u.ustuck) {
  577.         You("are being held, and cannot go up.");
  578.         return(1);
  579.     }
  580.     if(near_capacity() > SLT_ENCUMBER) {
  581.         /* No levitation check; inv_weight() already allows for it */
  582.         Your("load is too heavy to climb the %s.",
  583.             levl[u.ux][u.uy].typ == STAIRS ? "stairs" : "ladder");
  584.         return(1);
  585.     }
  586.     if(ledger_no(&u.uz) == 1) {
  587.         if (yn("Beware, there will be no return! Still climb?") != 'y')
  588.             return(0);
  589.     }
  590. #ifdef WALKIES
  591.     if(!next_to_u()) {
  592.         You("are held back by your pet!");
  593.         return(0);
  594.     }
  595. #endif
  596.     if (levl[u.ux][u.uy].typ == LADDER) at_ladder = TRUE;
  597.     prev_level(TRUE);
  598.     at_ladder = FALSE;
  599.     return(1);
  600. }
  601.  
  602. d_level save_dlevel = {0, 0};
  603.  
  604. /* check that we can write out the current level */
  605. static int
  606. currentlevel_rewrite()
  607. {
  608.     register int fd;
  609.  
  610.     /* since level change might be a bit slow, flush any buffered screen
  611.      *  output (like "you fall through a trapdoor") */
  612.     mark_synch();
  613.  
  614.     fd = create_levelfile(ledger_no(&u.uz));
  615.  
  616.     if(fd < 0) {
  617.         /*
  618.          * This is not quite impossible: e.g., we may have
  619.          * exceeded our quota. If that is the case then we
  620.          * cannot leave this level, and cannot save either.
  621.          * Another possibility is that the directory was not
  622.          * writable.
  623.          */
  624.         pline("Cannot create level file for level %d.",
  625.                         ledger_no(&u.uz));
  626.         return -1;
  627.     }
  628.  
  629. #ifdef MFLOPPY
  630.     if (!savelev(fd, ledger_no(&u.uz), COUNT_SAVE)) {
  631.         (void) close(fd);
  632.         delete_levelfile(ledger_no(&u.uz));
  633.         pline("NetHack is out of disk space for making levels!");
  634.         You("can save, quit, or continue playing.");
  635.         return -1;
  636.     }
  637. #endif
  638.     return fd;
  639. }
  640.  
  641. #ifdef INSURANCE
  642. void
  643. save_currentstate()
  644. {
  645.     int fd;
  646.  
  647.     if (flags.ins_chkpt) {
  648.         /* write out just-attained level, with pets and everything */
  649.         fd = currentlevel_rewrite();
  650.         if(fd < 0) return;
  651.         bufon(fd);
  652.         savelev(fd,ledger_no(&u.uz), WRITE_SAVE);
  653.         bclose(fd);
  654.     }
  655.  
  656.     /* write out non-level state */
  657.     savestateinlock();
  658. }
  659. #endif
  660.  
  661. /*
  662. static boolean
  663. badspot(x, y)
  664. register xchar x, y;
  665. {
  666.     return((levl[x][y].typ != ROOM && levl[x][y].typ != AIR &&
  667.              levl[x][y].typ != CORR) || MON_AT(x, y));
  668. }
  669. */
  670.  
  671. void
  672. goto_level(newlevel, at_stairs, falling, portal)
  673. d_level *newlevel;
  674. register boolean at_stairs, falling, portal;
  675. {
  676.     register int fd;
  677.     register boolean up = (depth(newlevel) < depth(&u.uz));
  678.     register boolean newdungeon = (u.uz.dnum != newlevel->dnum);
  679. #ifdef REINCARNATION
  680.     int new = 0;    /* made a new level? */
  681. #endif
  682.  
  683.     if (dunlev(newlevel) > dunlevs_in_dungeon(newlevel))
  684.         newlevel->dlevel = dunlevs_in_dungeon(newlevel);
  685.     if (newdungeon && In_endgame(newlevel)) { /* 1st Endgame Level !!! */
  686.         if (u.uhave.amulet)
  687.             assign_level(newlevel, &earth_level);
  688.         else return;
  689.     }
  690.     if (ledger_no(newlevel) <= 0)
  691.         done(ESCAPED);    /* in fact < 0 is impossible */
  692.     /* If you have the amulet and are trying to get out of Hell, going
  693.      * up a set of stairs sometimes does some very strange things!
  694.      */
  695.     if (Inhell && up && !newdungeon && u.uhave.amulet &&
  696.                 (dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz)-3)) {
  697.         if (!rn2(4)) {
  698.             if (u.ualign.type == A_CHAOTIC ||
  699.                 (u.ualign.type == A_NEUTRAL && rn2(2)))
  700.             assign_level(newlevel, &u.uz);
  701.             else
  702.             assign_rnd_level(newlevel, &u.uz, rnd(3));
  703.  
  704.             pline("A mysterious force momentarily surrounds you...");
  705.             if (on_level(newlevel, &u.uz)) {
  706.             (void) safe_teleds();
  707. #ifdef WALKIES
  708.             (void) next_to_u();
  709. #endif
  710.             return;
  711.             }
  712.         }
  713.     }
  714. #ifdef MULDGN
  715.     /* Prevent the player from going past the first quest level unless
  716.      * (s)he has been given the go-ahead by the leader.
  717.      */
  718.     if (on_level(&u.uz, &qstart_level) && !newdungeon && !ok_to_quest()) {
  719.  
  720.         pline("A mysterious force prevents you from descending.");
  721.         return;
  722.     }
  723. #endif
  724.     if (on_level(newlevel, &u.uz)) return;        /* this can happen */
  725.  
  726.     fd = currentlevel_rewrite();
  727.     if (fd < 0) return;
  728.  
  729.     if (falling) /* assuming this is only trapdoor */
  730.         impact_drop((struct obj *)0, u.ux, u.uy, newlevel->dlevel);
  731.  
  732.     check_special_room(TRUE);        /* probably was a trap door */
  733.     if (Punished) unplacebc();
  734.     u.utrap = 0;                /* needed in level_tele */
  735.     fill_pit(u.ux, u.uy);
  736.     u.ustuck = 0;                /* idem */
  737.     u.uinwater = 0;
  738.     keepdogs();
  739.     if (u.uswallow)                /* idem */
  740.         u.uswldtim = u.uswallow = 0;
  741.     /*
  742.      *  We no longer see anything on the level.  Make sure that this
  743.      *  follows u.uswallow set to null since uswallow overrides all
  744.      *  normal vision.
  745.      */
  746.     vision_recalc(2);
  747.     bufon(fd);
  748.     savelev(fd,ledger_no(&u.uz), WRITE_SAVE | FREE_SAVE);
  749.     bclose(fd);
  750.  
  751. #ifdef REINCARNATION
  752.     if (Is_rogue_level(newlevel) || Is_rogue_level(&u.uz))
  753.         assign_rogue_graphics(Is_rogue_level(newlevel));
  754. #endif
  755.     assign_level(&u.uz0, &u.uz);
  756.     assign_level(&u.uz, newlevel);
  757.     assign_level(&u.utolev, newlevel);
  758.     u.utotype = 0;
  759.     if (dunlev_reached(&u.uz) < dunlev(&u.uz))
  760.         dunlev_reached(&u.uz) = dunlev(&u.uz);
  761.  
  762.     /* set default level change destination areas */
  763.     /* the special level code may override these */
  764.     (void) memset((genericptr_t) &updest, 0, sizeof updest);
  765.     (void) memset((genericptr_t) &dndest, 0, sizeof dndest);
  766.  
  767.     if (In_endgame(&u.uz) ||
  768. #ifdef MFLOPPY
  769.         /* If the level has no .where yet, it hasn't been made */
  770.         !fileinfo[ledger_no(&u.uz)].where) {
  771. #else
  772.         !level_exists[ledger_no(&u.uz)]) {
  773. #endif
  774.         mklev();
  775. #ifdef REINCARNATION
  776.         new = 1;    /* made the level */
  777. #endif
  778.     } else {
  779.         fd = open_levelfile(ledger_no(&u.uz));
  780.         if (fd < 0) {
  781.             pline("Cannot open file (#%d) for level %d (errno %d).",
  782.                     ledger_no(&u.uz), depth(&u.uz), errno);
  783.             pline("Probably someone removed it.");
  784.             done(TRICKED);
  785.         }
  786.         minit();    /* ZEROCOMP */
  787.         getlev(fd, hackpid, ledger_no(&u.uz), FALSE);
  788.         (void) close(fd);
  789.     }
  790.  
  791.     if (portal && !In_endgame(&u.uz)) {
  792.         /* find the portal on the new level */
  793.         register struct trap *ttrap;
  794.  
  795.         for (ttrap = ftrap; ttrap; ttrap = ttrap->ntrap)
  796.         if (ttrap->ttyp == MAGIC_PORTAL) break;
  797.  
  798.         if (!ttrap) panic("goto_level: no corresponding portal!");
  799.         u.ux = ttrap->tx;
  800.         u.uy = ttrap->ty;
  801.     } else if (at_stairs && !In_endgame(&u.uz)) {
  802.         if (up) {
  803.         if (at_ladder) {
  804.             u.ux = xdnladder;
  805.             u.uy = ydnladder;
  806.         } else {
  807.             if (newdungeon) {
  808.             if (Is_stronghold(&u.uz)) {
  809.                 register xchar x, y;
  810.  
  811.                 do {
  812.                 x = (COLNO - 2 - rnd(5));
  813.                 y = rn1(ROWNO - 4, 3);
  814.                 } while(occupied(x, y) ||
  815.                     IS_WALL(levl[x][y].typ));
  816.                 u.ux = x;
  817.                 u.uy = y;
  818.             } else u_on_sstairs();
  819.             } else u_on_dnstairs();
  820.         }
  821.         /* Remove bug which crashes with levitation/punishment  KAA */
  822.         if (Punished && !Levitation) {
  823.             pline("With great effort you climb the %s.",
  824.                 at_ladder ? "ladder" : "stairs");
  825.         } else if (at_ladder)
  826.             You("climb up the ladder.");
  827.         } else {    /* down */
  828.         if (at_ladder) {
  829.             u.ux = xupladder;
  830.             u.uy = yupladder;
  831.         } else {
  832.             if (newdungeon) u_on_sstairs();
  833.             else u_on_upstairs();
  834.         }
  835.         if (u.dz &&
  836.             (near_capacity() > UNENCUMBERED || Punished || Fumbling)) {
  837.             You("fall down the %s.", at_ladder ? "ladder" : "stairs");
  838.             if (Punished) {
  839.             drag_down();
  840.             if (carried(uball)) {
  841.                 if (uwep == uball)
  842.                 setuwep((struct obj *)0);
  843.                 freeinv(uball);
  844.             }
  845.             }
  846.             losehp(rnd(3), "falling downstairs", KILLED_BY);
  847.             selftouch("Falling, you");
  848.         } else if (u.dz && at_ladder)
  849.             You("climb down the ladder.");
  850.         }
  851.     } else {    /* trap door or level_tele or In_endgame */
  852.         if (up)
  853.         place_lregion(updest.lx, updest.ly,
  854.                 updest.hx, updest.hy,
  855.                 updest.nlx, updest.nly,
  856.                 updest.nhx, updest.nhy,
  857.                 LR_UPTELE, (d_level *) 0);
  858.         else
  859.         place_lregion(dndest.lx, dndest.ly,
  860.                 dndest.hx, dndest.hy,
  861.                 dndest.nlx, dndest.nly,
  862.                 dndest.nhx, dndest.nhy,
  863.                 LR_DOWNTELE, (d_level *) 0);
  864.         if (falling) {
  865.         if (Punished) ballfall();
  866.         selftouch("Falling, you");
  867.         }
  868.     }
  869.  
  870.     if (Punished) placebc();
  871.     losedogs();
  872.     obj_delivery();
  873.  
  874.     initrack();
  875.  
  876.     if(MON_AT(u.ux, u.uy)) mnexto(m_at(u.ux, u.uy));
  877.     if(MON_AT(u.ux, u.uy)) {
  878.         impossible("mnexto failed (do.c)?");
  879.         rloc(m_at(u.ux, u.uy));
  880.     }
  881.     remove_cadavers(&fobj);    /* remove rotted meat (before seen) */
  882.  
  883.     /* initial movement of bubbles just before vision_recalc */
  884.     if (Is_waterlevel(&u.uz))
  885.         movebubbles();
  886.  
  887.     /* Reset the screen. */
  888.     vision_reset();        /* reset the blockages */
  889.     docrt();        /* does a full vision recalc */
  890.  
  891.     /* give room entrance message, if any */
  892.     check_special_room(FALSE);
  893.  
  894.     /* In Nethack 3.1, Gehennom starts after the stronghold.  Moreover,
  895.      * there are traps in the stronghold, that can send the player
  896.      * to Gehennom (gnark, gnark)!  So we have to test here:
  897.      */
  898.     if(!In_hell(&u.uz0) && Inhell) {
  899.         if(Is_valley(newlevel)) {
  900.         You("arrive at the Valley of the Dead...");
  901.         pline("The odor of burnt flesh and decay pervades the air.");
  902. #ifdef MICRO
  903.         display_nhwindow(WIN_MESSAGE, FALSE);
  904. #endif
  905.         You("hear groans and moans everywhere.");
  906.         } else pline("It is hot here.  You smell smoke...");
  907.     }
  908.  
  909. #ifdef REINCARNATION
  910.     /*
  911.      *  Move all plines beyond the screen reset.
  912.      */
  913.     if (new && Is_rogue_level(&u.uz))
  914.         You("enter what seems to be an older, more primitive world.");
  915. #endif
  916.     /* Final confrontation */
  917.     if (In_endgame(&u.uz) && newdungeon && u.uhave.amulet &&
  918.                            flags.no_of_wizards == 0)
  919.         resurrect();
  920.     if (newdungeon && In_tower(&u.uz))
  921.         pline("The heat and smoke are gone.");
  922. #ifdef MULDGN
  923.     /* the message from your quest leader */
  924.     if (!In_quest(&u.uz0) && at_dgn_entrance("The Quest") &&
  925.         !(u.uevent.qexpelled || u.uevent.qcompleted || leaderless())) {
  926.  
  927.         if (u.uevent.qcalled) {
  928.             com_pager(3);
  929.         } else {
  930.             com_pager(2);
  931.             u.uevent.qcalled = TRUE;
  932.         }
  933.     }
  934.  
  935.     if(Is_knox(&u.uz)) {
  936.         register struct monst *mtmp;
  937.  
  938.         You("penetrated a high security area!");
  939.         pline("An alarm sounds!");
  940.         for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  941.             if(mtmp->msleep) mtmp->msleep = 0;
  942.     }
  943. #endif /* MULDGN */
  944.     if(on_level(&u.uz, &astral_level)) {
  945.         register struct monst *mtmp;
  946.  
  947.         /* reset monster hostility relative to player */
  948.         for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  949.             reset_hostility(mtmp);
  950.  
  951.         /* create some player-monsters */
  952.         create_mplayers(rn1(4, 3), TRUE);
  953.  
  954.         /* create a guardian angel next to player, if worthy */
  955.         if (Conflict) {
  956.             coord mm;
  957.             int i = rnd(4);
  958.     pline("A voice booms: \"Thy desire for conflict shall be fulfilled!\"");
  959.             while(i--) {
  960.             mm.x = u.ux;
  961.             mm.y = u.uy;
  962.             if(enexto(&mm, mm.x, mm.y, &mons[PM_ANGEL]))
  963.                 (void) mk_roamer(&mons[PM_ANGEL], u.ualign.type,
  964.                         mm.x, mm.y, FALSE);
  965.             }
  966.  
  967.         } else if(u.ualign.record > 8 /* fervent */) {
  968.             coord mm;
  969.  
  970.         pline("A voice whispers: \"Thou hast been worthy of me!\"");
  971.             mm.x = u.ux;
  972.             mm.y = u.uy;
  973.             if (enexto(&mm, mm.x, mm.y, &mons[PM_ANGEL])) {
  974.             if ((mtmp = mk_roamer(&mons[PM_ANGEL], u.ualign.type,
  975.                        mm.x, mm.y, TRUE)) != 0) {
  976.                 register struct obj *otmp;
  977.  
  978.                 if (!Blind)
  979.                 pline("An angel appears near you.");
  980.                 else
  981.             You("feel the presence of a friendly angel near you.");
  982.                 /* guardian angel -- the one case mtame doesn't
  983.                  * imply an edog structure, so we don't want to
  984.                  * call tamedog().
  985.                  */
  986.                 mtmp->mtame = 10;
  987.                 /* make him strong enough vs. endgame foes */
  988.                 mtmp->m_lev = rn1(8,15);
  989.                 mtmp->mhp = mtmp->mhpmax =
  990.                     d((int)mtmp->m_lev,10) + 30 + rnd(30);
  991.                 if ((otmp = select_hwep(mtmp)) == 0) {
  992.                 otmp = mksobj(SILVER_SABER, FALSE, FALSE);
  993.                 mpickobj(mtmp, otmp);
  994.                 }
  995.                 bless(otmp);
  996.                 if (otmp->spe < 4) otmp->spe += rnd(4);
  997. #ifdef MUSE
  998.                 if ((otmp = which_armor(mtmp, W_ARMS)) == 0
  999.                   || otmp->otyp != SHIELD_OF_REFLECTION) {
  1000.                 (void) mongets(mtmp, AMULET_OF_REFLECTION);
  1001.                 m_dowear(mtmp, TRUE);
  1002.                 }
  1003. #endif
  1004.             }
  1005.             }
  1006.         }
  1007.     }
  1008.  
  1009. #ifdef MULDGN
  1010.     onquest();
  1011. #endif
  1012.     assign_level(&u.uz0, &u.uz); /* reset u.uz0 */
  1013.  
  1014. #ifdef INSURANCE
  1015.     save_currentstate();
  1016. #endif
  1017.  
  1018.     pickup(1);
  1019. }
  1020.  
  1021. /* handle something like portal ejection */
  1022. void
  1023. deferred_goto()
  1024. {
  1025.     if (!on_level(&u.uz, &u.utolev)) {
  1026.         d_level dest;
  1027.         int typmask = u.utotype; /* save it; goto_level zeroes u.utotype */
  1028.  
  1029.         assign_level(&dest, &u.utolev);
  1030.         goto_level(&dest, !!(typmask&4), !!(typmask&2), !!(typmask&1));
  1031.         if (typmask & 0200) {    /* remove portal */
  1032.         deltrap(t_at(u.ux, u.uy));
  1033.         newsym(u.ux, u.uy);
  1034.         }
  1035.     }
  1036. }
  1037.  
  1038. #endif /* OVL2 */
  1039. #ifdef OVL3
  1040.  
  1041. void
  1042. revive_corpse(corpse, odds, mark_as_old)    /* see remove_cadavers() */
  1043. register struct obj *corpse;
  1044. int odds;
  1045. boolean mark_as_old;
  1046. {
  1047.     register struct monst *mtmp;
  1048.  
  1049.     corpse->oldcorpse = mark_as_old;
  1050.  
  1051.     /* odds == 0 is a special case meaning 'always revive' */
  1052.     if (!odds || !rn2(odds)) {
  1053.     if (carried(corpse)) {
  1054.         if (corpse == uwep) {
  1055.         if ((mtmp = revive(corpse,TRUE)) != 0)
  1056.             pline("The %s%s %s writhes out of your grasp!",
  1057.             (mtmp->mhp < mtmp->mhpmax) ? "bite-covered ":"",
  1058.                 mtmp->data->mname, xname(corpse));
  1059.         } else if ((mtmp = revive(corpse,TRUE)) != 0)
  1060.         You("feel squirming in your backpack!");
  1061.     } else {
  1062.         if ((mtmp = revive(corpse,FALSE)) && cansee(mtmp->mx,mtmp->my))
  1063.         pline("%s rises from the dead!",
  1064.             (mtmp->mhp==mtmp->mhpmax) ? Monnam(mtmp)
  1065.             : Adjmonnam(mtmp, "bite-covered"));
  1066.     }
  1067.     }
  1068. }
  1069.  
  1070. /*
  1071.  *  Remove old cadavers from any object chain.  Regenerate trolls
  1072.  *  thanks to KAA.  Follows containers (except ice boxes).
  1073.  */
  1074. #define TAINT_AGE    50    /* min. limit for tainting.  see eat.c */
  1075. #define ODDS_RV1    37    /* 1/37 odds for 50 moves = 75% revive */
  1076. #define ODDS_RV2    2    /* special case 1/2 odds of reviving */
  1077.  
  1078. void
  1079. remove_cadavers(chain)
  1080. struct obj **chain;
  1081. {
  1082.     register struct obj *obj, *nobj, *pobj = (struct obj *)0;
  1083.     register long corpse_age;
  1084.     boolean ininv = (*chain == invent);
  1085.     boolean onfloor = (*chain == fobj);
  1086.     boolean buried = (*chain == level.buriedobjlist);
  1087.  
  1088.     for (obj = *chain; obj; obj = nobj) {
  1089.     nobj = obj->nobj;
  1090.  
  1091.     if (obj->otyp == CORPSE) {
  1092.         /* corpses laying on ice deteriorate more slowly */
  1093.         if (onfloor && obj->age < monstermoves &&
  1094.         rn2(3) && is_ice(obj->ox, obj->oy)) obj->age++;
  1095.         corpse_age = monstermoves - obj->age;
  1096.  
  1097.         if (is_rider(&mons[obj->corpsenm]) && corpse_age >= 12 && onfloor) {
  1098.         /* these always come back eventually */
  1099.         /* riders can't be picked up, but can be buried, but
  1100.          * the astral level seems to rule out that possibility
  1101.          */
  1102.         revive_corpse(obj, 3, FALSE);
  1103.         } else if (mons[obj->corpsenm].mlet == S_TROLL && !obj->oldcorpse
  1104.                && !(mons[obj->corpsenm].geno & (G_GENOD | G_EXTINCT))
  1105.                && (onfloor || ininv)) {
  1106.  
  1107.         /* the corpse has 50 moves, the lower limit for tainting,
  1108.          * to attempt re-animation.  if it is unsuccessful it is
  1109.          * marked to prevent further attempts.  if we leave the
  1110.          * level and return to old corpses that haven't been marked
  1111.          * they're given a one-shot chance to re-animate.
  1112.          */
  1113.         if (corpse_age < TAINT_AGE)
  1114.             revive_corpse(obj, ODDS_RV1, FALSE);
  1115.         else if (corpse_age == TAINT_AGE)
  1116.             revive_corpse(obj, ODDS_RV1, TRUE);
  1117.         else revive_corpse(obj, ODDS_RV2, TRUE);
  1118.  
  1119.         } else if (obj->corpsenm != PM_LIZARD && (250 < corpse_age)) {
  1120.         if(ininv)
  1121.             useup(obj);
  1122.         else if(onfloor)
  1123.             delobj(obj);
  1124.         else if(buried)
  1125.             delburiedobj(obj);
  1126.         else { /* in a container */
  1127.             if(pobj) pobj->nobj = nobj;
  1128.             else *chain = nobj;
  1129.             obfree(obj, (struct obj *) 0);
  1130.             obj = 0;
  1131.         }
  1132.         }
  1133.     } else if (Has_contents(obj) && obj->otyp != ICE_BOX) {
  1134.         remove_cadavers(&obj->cobj);
  1135.     }
  1136.     /* pobj is only used for containers, which don't allow revive() -dlc */
  1137.     /* and for monster inventory (special cases only) under MUSE */
  1138.     if (obj) pobj = obj;
  1139.     }
  1140. }
  1141.  
  1142. int
  1143. donull()
  1144. {
  1145.     return(1);    /* Do nothing, but let other things happen */
  1146. }
  1147.  
  1148. #endif /* OVL3 */
  1149. #ifdef OVLB
  1150.  
  1151. STATIC_PTR int
  1152. wipeoff()
  1153. {
  1154.     if(u.ucreamed < 4)    u.ucreamed = 0;
  1155.     else            u.ucreamed -= 4;
  1156.     if (Blinded < 4)    Blinded = 0;
  1157.     else            Blinded -= 4;
  1158.     if (!Blinded) {
  1159.         pline("You've got the glop off.");
  1160.         u.ucreamed = 0;
  1161.         Blinded = 1;
  1162.         make_blinded(0L,TRUE);
  1163.         return(0);
  1164.     } else if (!u.ucreamed) {
  1165.         Your("%s feels clean now.", body_part(FACE));
  1166.         return(0);
  1167.     }
  1168.     return(1);        /* still busy */
  1169. }
  1170.  
  1171. int
  1172. dowipe()
  1173. {
  1174.     if(u.ucreamed)  {
  1175.         static NEARDATA char buf[39];
  1176.  
  1177.         Sprintf(buf, "wiping off your %s", body_part(FACE));
  1178.         set_occupation(wipeoff, buf, 0);
  1179.         /* Not totally correct; what if they change back after now
  1180.          * but before they're finished wiping?
  1181.          */
  1182.         return(1);
  1183.     }
  1184.     Your("%s is already clean.", body_part(FACE));
  1185.     return(1);
  1186. }
  1187.  
  1188. #endif /* OVLB */
  1189. #ifdef OVL1
  1190.  
  1191. /* split obj so that it gets size num */
  1192. /* remainder is put in the object structure delivered by this call */
  1193. struct obj *
  1194. splitobj(obj, num)
  1195. register struct obj *obj;
  1196. register long num;
  1197. {
  1198. register struct obj *otmp;
  1199.     /* assert(0 < num && num < obj->quan); */
  1200.     otmp = newobj(obj->onamelth);
  1201.     *otmp = *obj;        /* copies whole structure */
  1202.     otmp->o_id = flags.ident++;
  1203.     obj->quan = num;
  1204.     obj->owt = weight(obj);
  1205.     otmp->quan -= num;
  1206.     otmp->owt = weight(otmp);    /* -= obj->owt ? */
  1207.     obj->nobj = obj->nexthere = otmp;
  1208.     if (obj->onamelth)
  1209.         (void)strncpy(ONAME(otmp), ONAME(obj), (int)obj->onamelth);
  1210.     if(obj->unpaid) splitbill(obj,otmp);
  1211.     return(otmp);
  1212. }
  1213.  
  1214. #endif /* OVL1 */
  1215. #ifdef OVLB
  1216.  
  1217. void
  1218. set_wounded_legs(side, timex)
  1219. register long side;
  1220. register int timex;
  1221. {
  1222.     if(!Wounded_legs) {
  1223.         ATEMP(A_DEX)--;
  1224.         flags.botl = 1;
  1225.     }
  1226.  
  1227.     if(!Wounded_legs || (Wounded_legs & TIMEOUT))
  1228.         Wounded_legs |= side + timex;
  1229.     else
  1230.         Wounded_legs |= side;
  1231. }
  1232.  
  1233. void
  1234. heal_legs()
  1235. {
  1236.     if(Wounded_legs) {
  1237.         if (ATEMP(A_DEX) < 0) {
  1238.             ATEMP(A_DEX)++;
  1239.             flags.botl = 1;
  1240.         }
  1241.  
  1242.         if((Wounded_legs & BOTH_SIDES) == BOTH_SIDES) {
  1243.             Your("%s feel somewhat better.",
  1244.                 makeplural(body_part(LEG)));
  1245.         } else {
  1246.             Your("%s feels somewhat better.",
  1247.                 body_part(LEG));
  1248.         }
  1249.         Wounded_legs = 0;
  1250.     }
  1251. }
  1252.  
  1253. #endif /* OVLB */
  1254.  
  1255. /*do.c*/
  1256.